/*
 * Copyright (c) 2010, Apropos Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name Apropos nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package org.apropos.ui;

import javafx.scene.chart.PieChart;
import javafx.scene.control.Label;
import javafx.scene.text.Font;
import org.jfxtras.scene.layout.XHBox;
import org.jfxtras.scene.layout.XLayoutInfo;
import org.jfxtras.scene.layout.XLayoutInfo.*;
import org.jfxtras.scene.layout.XVBox;
import org.jfxtras.scene.control.XPicker;
import org.apropos.model.Release;
import javafx.scene.control.CheckBox;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.Chart;
import javafx.scene.chart.part.ValueAxis;
import javafx.scene.chart.part.CategoryAxis;
import javafx.scene.chart.part.NumberAxis;
import javafx.util.Sequences;

/**
 * @author Stephen Chin
 */
public class AnalyzeModule extends AbstractModulePage {

//    def releaseChoice:ChoiceBox = ChoiceBox {
//        items: bind model.releases
//        var selIndex = bind releaseChoice.selectedIndex on replace {
//          if (selIndex >= 0) {
//            rebuildChart();
//          }
//        }
//    }
//
//    def release = bind releaseChoice.selectedItem as Release;

    def release = bind releaseChoice.selectedItem as Release;

    public var selectedIndex:Integer = -1 on replace {
        if (releaseChoice.selectedIndex != selectedIndex) {
            releaseChoice.select(selectedIndex);
        }
        if (selectedIndex >= 0) {
          rebuildChart();
        }
    }

    var inScopeIndex:Integer = -1;

    public var inScope:String = bind if (inScopeIndex <= 0) "YN" else if (inScopeIndex == 1) "Y" else "N" on replace {
        if (inScopeIndex >= 0) {
          rebuildChart();
        }
    }

    var releaseChoice:XPicker = XPicker {
        firstLetter: true
        promptText: "Please choose ..."
        //id: "JFXtras Shapes"
        layoutInfo: XLayoutInfo {
//            hfill: true
//            maxWidth: 4000
            width: 160
        }
        items: bind model.releases
        onIndexChange: function(index) {
            selectedIndex = index;
        }
    }
    def inScopeFilter = Filter {
        name: "In Scope"
        list: ["Yes", "No"]
        visible: bind not barChart
        selectedIndex: bind inScopeIndex with inverse
    }

    def names = bind model.allocationNames;

    def parentBind = bind parent on replace {
        if (parent != null) {
            rebuildChart();
        }
    }

    var chart:Chart;
    var showLabels = true;
    var barChart:Boolean on replace {
        if (isInitialized(barChart)) {
            rebuildChart();
        }
    }

    var showActual = bind model.showActual on replace {
        rebuildChart();
    }

    function rebuildChart():Void {
        def categories = for (name in names where release.getAllocationTotals(name, "YN") > 0) name;
        chart = if (barChart) BarChart {
            def series = [
                BarChart.Series {
                    name: "In Scope"
                    data: for (name in categories) BarChart.Data {
                        category: name
                        value: release.getAllocationTotals(name, "Y")
                    }
                }
                BarChart.Series {
                    name: "Out of Scope"
                    data: for (name in categories) BarChart.Data {
                        category: name
                        value: release.getAllocationTotals(name, "N")
                    }
                }
            ]
            categoryAxis: CategoryAxis {
              categories: categories
            }
            valueAxis: NumberAxis {
              lowerBound: 0
              upperBound: Sequences.max(for (name in names) release.getAllocationTotals(name, "YN")) as Number
              tickUnit: 100
            }
            titleFont: Font.font(null, 24)
            title: bind "Investment Allocation for {releaseChoice.selectedItem}"
            data: series
            legendVisible: true
            layoutInfo: XLayoutInfo {hgrow: ALWAYS, vgrow: ALWAYS, vfill: true, hfill: true}
        } else PieChart {
            def data = for (name in names where release.getAllocationTotals(name, inScope) > 0) {
                PieChart.Data {
                    label: name
                    value: release.getAllocationTotals(name, inScope)
                }
            }
            titleFont: Font.font(null, 24)
            title: bind "Investment Allocation for {releaseChoice.selectedItem}"
            data: data
            pieLabelVisible: bind showLabels
            legendVisible: true
            layoutInfo: XLayoutInfo {hgrow: ALWAYS, vgrow: ALWAYS, vfill: true, hfill: true}
        }
    }
    
    def pickers = XHBox {
        spacing: 8
        content: [
            CheckBox {
                text: "Show as Bar Chart"
                selected: bind barChart with inverse
            }
            Label {
                text: "Release:"
            }
            releaseChoice,
            inScopeFilter
        ]
    }

    init {
        pageToolBar = PageToolBar {
            leftNodes: pickers
            rightNodes: CostSelectionNode {}
        }
        pageContent = XVBox {
            content: bind [
                chart,
                CheckBox {
                    text: "Show Labels"
                    selected: bind showLabels with inverse
                }
            ]
        }
        releaseChoice.select(0);
    }
}
